package setting

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"likeadmin/admin/schemas/req"
	"likeadmin/admin/schemas/resp"
	"likeadmin/core/request"
	"likeadmin/core/response"
	"likeadmin/dao"
	"likeadmin/model"
	"likeadmin/util"
)

type ISettingChannelService interface {
	MpDetail(c *gin.Context) (res resp.ChannelMnpSettingResp, e error)
	MpEdit(editReq req.ChannelMnpSettingReq) (e error)
	OpenDetail() (res resp.ChannelOpenSettingResp, e error)
	OpenEdit(editReq req.ChannelOpenSettingReq) (e error)
	OADetail(c *gin.Context) (res resp.ChannelOASettingResp, e error)
	OAEdit(editReq req.ChannelOASettingReq) (e error)
	OaMenuDetail() (res []resp.ChannelOaMenuResp, e error)
	OaMenuEdit(editReq []req.ChannelOaMenuReq) (e error)
	H5Detail(c *gin.Context) (res resp.ChannelH5SettingResp, e error)
	H5Edit(editReq req.ChannelH5SettingReq) (e error)
	OaReplyList(c *gin.Context, Req request.PageReq, listReq req.OfficialReplyListReq) (res response.PageResp, e error)
	OaReplyAdd(c *gin.Context, addReq req.OfficialReplyAddReq) (e error)
	OaReplyEdit(c *gin.Context, editReq req.OfficialReplyEditReq) (e error)
	OaReplyStatus(c *gin.Context, id int32) (e error)
	OaReplyDel(c *gin.Context, id int32) (e error)
	OaReplyDetail(c *gin.Context, id int32) (res resp.OfficialReplyResp, e error)
}

// NewSettingChannelService 初始化
func NewSettingChannelService(db *gorm.DB, dao *dao.Query) ISettingChannelService {
	return &settingChannelService{db: db, dao: dao}
}

// settingChannelService 渠道配置服务实现类
type settingChannelService struct {
	db  *gorm.DB
	dao *dao.Query
}

var defaultStr = "{\"name\":\"\",\"original_id\":\"\",\"qr_code\":\"\",\"app_id\":\"\",\"app_secret\":\"\"}"

// Detail 详情
func (sSrv settingChannelService) MpDetail(c *gin.Context) (res resp.ChannelMnpSettingResp, e error) {
	data, err := util.ConfigUtil.GetVal(sSrv.db, "channel", "mnp", defaultStr)
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	err = util.ToolsUtil.JsonToObj(data, &res)
	if err != nil {
		if e = response.CheckErr(err, "JsonToObj err"); e != nil {
			return
		}
	}
	if res.QrCode != "" {
		res.QrCode = util.UrlUtil.ToAbsoluteUrl(res.QrCode)
	}
	res.BusinessDomain = util.ServerUtil.GetDomainWithoutPort(c.Request.Host)
	res.UdpDomain = "udp://" + util.ServerUtil.GetDomainWithoutPort(c.Request.Host)
	res.DownloadFileDomain = "https://" + util.ServerUtil.GetDomainWithoutPort(c.Request.Host)
	res.UploadFileDomain = "https://" + util.ServerUtil.GetDomainWithoutPort(c.Request.Host)
	res.RequestDomain = "https://" + util.ServerUtil.GetDomainWithoutPort(c.Request.Host)
	res.SocketDomain = "wss://" + util.ServerUtil.GetDomainWithoutPort(c.Request.Host)

	return
}

// Edit 保存
func (sSrv settingChannelService) MpEdit(editReq req.ChannelMnpSettingReq) (e error) {
	if editReq.QrCode != "" {
		editReq.QrCode = util.UrlUtil.ToRelativeUrl(editReq.QrCode)
	}

	marshal, err := json.Marshal(editReq)
	if err != nil {
		if e = response.CheckErr(err, "Save Set name err"); e != nil {
			return
		}
	}

	err = util.ConfigUtil.Set(sSrv.db, "channel", "mnp", string(marshal))
	if e = response.CheckErr(err, "Save Set name err"); e != nil {
		return
	}
	//清空缓存
	util.RedisUtil.HDel("channel", "mnp")
	return
}

var defaultOpenStr = "{\"app_id\":\"\",\"app_secret\":\"\"}"

// OpenDetail 详情
func (sSrv settingChannelService) OpenDetail() (res resp.ChannelOpenSettingResp, e error) {
	data, err := util.ConfigUtil.GetVal(sSrv.db, "channel", "open", defaultOpenStr)
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	err = util.ToolsUtil.JsonToObj(data, &res)
	if err != nil {
		if e = response.CheckErr(err, "JsonToObj err"); e != nil {
			return
		}
	}
	return
}

// OpenEdit 保存
func (sSrv settingChannelService) OpenEdit(editReq req.ChannelOpenSettingReq) (e error) {

	marshal, err := json.Marshal(editReq)
	if err != nil {
		if e = response.CheckErr(err, "Save Set name err"); e != nil {
			return
		}
	}

	err = util.ConfigUtil.Set(sSrv.db, "channel", "open", string(marshal))
	if e = response.CheckErr(err, "Save Set name err"); e != nil {
		return
	}

	//清空缓存
	util.RedisUtil.HDel("channel", "open")
	return
}

var defaultOAStr = "{\"app_id\":\"\",\"app_secret\":\"\",\"encryption_type\": 1}"

// OADetail 详情
func (sSrv settingChannelService) OADetail(c *gin.Context) (res resp.ChannelOASettingResp, e error) {
	data, err := util.ConfigUtil.GetVal(sSrv.db, "channel", "oa", defaultOAStr)
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	err = util.ToolsUtil.JsonToObj(data, &res)
	if err != nil {
		if e = response.CheckErr(err, "JsonToObj err"); e != nil {
			return
		}
	}
	if res.QrCode != "" {
		res.QrCode = util.UrlUtil.ToAbsoluteUrl(res.QrCode)
	}

	host := util.ServerUtil.GetDomainWithoutPort(c.Request.Host)
	// 判断请求是否使用了TLS加密
	isTLS := c.Request.TLS != nil
	scheme := "http"
	if isTLS {
		scheme = "https"
	}
	res.BusinessDomain = host
	res.JsSecureDomain = host
	res.WebAuthDomain = host
	res.Url = fmt.Sprintf("%s://%s/%s", scheme, host, "channel/oa/index")
	return
}

// OAEdit 保存
func (sSrv settingChannelService) OAEdit(editReq req.ChannelOASettingReq) (e error) {
	if editReq.QrCode != "" {
		editReq.QrCode = util.UrlUtil.ToRelativeUrl(editReq.QrCode)
	}

	marshal, err := json.Marshal(editReq)
	if err != nil {
		if e = response.CheckErr(err, "Save Set name err"); e != nil {
			return
		}
	}

	err = util.ConfigUtil.Set(sSrv.db, "channel", "oa", string(marshal))
	if e = response.CheckErr(err, "Save Set name err"); e != nil {
		return
	}

	//清空缓存
	util.RedisUtil.HDel("channel", "oa")
	return
}

// OaMenuDetail 详情
func (sSrv settingChannelService) OaMenuDetail() (res []resp.ChannelOaMenuResp, e error) {
	data, err := util.ConfigUtil.GetVal(sSrv.db, "channel_oa", "menus", "")
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	if data == "" {
		return res, nil
	}

	err = util.ToolsUtil.JsonToObj(data, &res)
	if err != nil {
		if e = response.CheckErr(err, "JsonToObj err"); e != nil {
			return
		}
	}
	return
}

// OaMenuEdit 保存菜单
func (sSrv settingChannelService) OaMenuEdit(editReq []req.ChannelOaMenuReq) (e error) {
	marshal, err := json.Marshal(editReq)
	if err != nil {
		if e = response.CheckErr(err, "Save Set name err"); e != nil {
			return
		}
	}

	err = util.ConfigUtil.Set(sSrv.db, "channel_oa", "menus", string(marshal))
	if e = response.CheckErr(err, "Save Set name err"); e != nil {
		return
	}

	return
}

var defaultH5Str = "{\"status\":0,\"page_status\":0,\"page_url\":\"\",\"url\":\"\"}"

// H5Detail 详情
func (sSrv settingChannelService) H5Detail(c *gin.Context) (res resp.ChannelH5SettingResp, e error) {
	data, err := util.ConfigUtil.GetVal(sSrv.db, "channel", "h5", defaultH5Str)
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	err = util.ToolsUtil.JsonToObj(data, &res)
	if err != nil {
		if e = response.CheckErr(err, "JsonToObj err"); e != nil {
			return
		}
	}

	host := util.ServerUtil.GetDomainWithoutPort(c.Request.Host)
	// 判断请求是否使用了TLS加密
	isTLS := c.Request.TLS != nil
	scheme := "http"
	if isTLS {
		scheme = "https"
	}
	res.Url = fmt.Sprintf("%s://%s/%s", scheme, host, "mobile")
	return
}

// H5Edit 保存
func (sSrv settingChannelService) H5Edit(editReq req.ChannelH5SettingReq) (e error) {
	marshal, err := json.Marshal(editReq)
	if err != nil {
		if e = response.CheckErr(err, "Save Set name err"); e != nil {
			return
		}
	}

	err = util.ConfigUtil.Set(sSrv.db, "channel", "h5", string(marshal))
	if e = response.CheckErr(err, "Save Set name err"); e != nil {
		return
	}

	//清空缓存
	util.RedisUtil.HDel("channel", "h5")
	return
}

// OaReplyList 回复列表
func (sSrv settingChannelService) OaReplyList(c *gin.Context, page request.PageReq, listReq req.OfficialReplyListReq) (res response.PageResp, e error) {
	// 分页信息
	limit := page.PageSize
	offset := page.PageSize * (page.PageNo - 1)

	m := sSrv.dao.OfficialReply
	q := m.WithContext(c)

	// 查询
	if listReq.ReplyType >= 0 {
		q = q.Where(m.ReplyType.Eq(listReq.ReplyType))
	}

	// 总数
	count, err := q.Count()
	if e = response.CheckErr(err, "List Count err"); e != nil {
		return
	}
	// 数据
	objs, err := q.Limit(limit).Offset(offset).Order(m.Sort.Desc()).Find()
	if e = response.CheckErr(err, "List Find err"); e != nil {
		return
	}
	var resp []resp.OfficialReplyResp
	response.Copy(&resp, objs)
	return response.PageResp{
		PageNo:   page.PageNo,
		PageSize: page.PageSize,
		Count:    count,
		Lists:    resp,
	}, nil
}

func (sSrv settingChannelService) OaReplyAdd(c *gin.Context, addReq req.OfficialReplyAddReq) (e error) {
	m := sSrv.dao.OfficialReply
	q := m.WithContext(c)

	var obj model.OfficialReply
	response.Copy(&obj, addReq)
	// 更新
	err := q.Create(&obj)

	e = response.CheckErr(err, "OaReplyAdd Create err")
	return
}

func (sSrv settingChannelService) OaReplyEdit(c *gin.Context, editReq req.OfficialReplyEditReq) (e error) {
	m := sSrv.dao.OfficialReply
	q := m.WithContext(c)

	obj := util.ConvertUtil.StructToMap(editReq)
	delete(obj, "Id")
	// 更新
	_, err := q.Where(m.ID.Eq(editReq.Id)).Updates(obj)
	if e = response.CheckErr(err, "Edit Updates err"); e != nil {
		return
	}

	return
}

func (sSrv settingChannelService) OaReplyStatus(c *gin.Context, id int32) (e error) {
	m := sSrv.dao.OfficialReply
	q := m.WithContext(c)

	first, err := q.Where(m.ID.Eq(id)).First()
	// 校验
	if e = response.CheckErrDBNotRecord(err, "change status 数据不存在!"); e != nil {
		return
	}

	// 更新
	if first.Status == 1 {
		_, err = q.Where(m.ID.Eq(id)).UpdateSimple(m.Status.Zero())
	} else {
		_, err = q.Where(m.ID.Eq(id)).UpdateSimple(m.Status.Value(1))
	}
	e = response.CheckErr(err, "Edit Updates err")
	return
}

func (sSrv settingChannelService) OaReplyDel(c *gin.Context, id int32) (e error) {
	m := sSrv.dao.OfficialReply
	q := m.WithContext(c)

	_, err := q.Where(m.ID.Eq(id)).First()
	// 校验
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "Del First err"); e != nil {
		return
	}
	// 删除
	_, err = q.Where(m.ID.Eq(id)).Delete()
	e = response.CheckErr(err, "Delete err")
	return
}

// OaReplyDetail 公众号的回复详情
func (sSrv settingChannelService) OaReplyDetail(c *gin.Context, id int32) (res resp.OfficialReplyResp, e error) {
	m := sSrv.dao.OfficialReply
	q := m.WithContext(c)

	obj, err := q.Where(m.ID.Eq(id)).First()
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "Detail First err"); e != nil {
		return
	}
	response.Copy(&res, obj)
	return
}
